package com.lanyun.auth.domain.authPermission.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.lanyun.auth.basic.entity.*;
import com.lanyun.auth.basic.service.*;
import com.lanyun.auth.controller.admin.authPermission.vo.AuthPermissionRequestVO;
import com.lanyun.auth.convert.authPermission.AuthPermissionConvert;
import com.lanyun.auth.domain.authPermission.AuthPermissionDomainService;
import com.lanyun.auth.enums.AuthConstant;
import com.lanyun.redis.util.CacheKey;
import com.lanyun.redis.util.RedisUtil;
import com.lanyun.web.enums.IsDeletedFlagEnum;
import com.lanyun.web.enums.IsEnabledFlagEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 权限领域service
 *
 * @Author Jqcc
 * @Version 1.0
 * @Data 2025/3/11
 */
@Service
@Slf4j
public class AuthPermissionDomainServiceImpl implements AuthPermissionDomainService {

    @Resource
    private AuthPermissionService authPermissionService;

    @Resource
    private AuthUserService authUserService;

    @Resource
    private AuthUserRoleService authUserRoleService;

    @Resource
    private AuthRolePermissionService authRolePermissionService;

    @Resource
    private AuthRoleService authRoleService;

    @Resource
    private RedisUtil redisUtil;


    @Override
    public Boolean add(AuthPermissionRequestVO authPermissionRequestVO) {
        AuthPermission authPermission = AuthPermissionConvert.INSTANCE.convert(authPermissionRequestVO);
        authPermission.setStatus(IsEnabledFlagEnum.ENABLED.getVal());
        // TODO 该处没有同步到redis
        return ObjectUtil.isNotNull(authPermissionService.insert(authPermission));
    }

    @Override
    public Boolean update(AuthPermissionRequestVO authPermissionRequestVO) {
        AuthPermission authPermission = AuthPermissionConvert.INSTANCE.convert(authPermissionRequestVO);
        return ObjectUtil.isNotNull(authPermissionService.update(authPermission));
    }

    @Override
    public Boolean delete(AuthPermissionRequestVO authPermissionRequestVO) {
        AuthPermission authPermission = new AuthPermission();
        authPermission.setId(authPermissionRequestVO.getId());
        authPermission.setStatus(IsEnabledFlagEnum.DISABLED.getVal());
        authPermission.setIsDeleted(IsDeletedFlagEnum.DELETED.getVal());
        return ObjectUtil.isNotNull(authPermissionService.update(authPermission));
    }

    @Override
    public List<String> getPermission(String userName) {

        String touristKey = redisUtil.buildKey(CacheKey.AUTH_PERMISSION.getCachePrefix(), "TOURIST");

        // 游客权限
        if (StringUtils.isBlank(userName)) {
            // 判断缓存中是否有这个key
            String cacheTouristKey = redisUtil.get(touristKey);
            if (StringUtils.isNotBlank(cacheTouristKey)) {
                List<String> cache = JSONUtil.parseArray(cacheTouristKey).toList(String.class);
                return cache;
            }


            AuthRole role = new AuthRole();
            role.setRoleKey(AuthConstant.TOURIST_USER);
            AuthRole authRole = authRoleService.queryByCondition(role);
            Long authRoleId = authRole.getId();
            AuthRolePermission authRolePermission = new AuthRolePermission();
            authRolePermission.setRoleId(authRoleId);
            authRolePermission.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
            List<AuthRolePermission> authRolePermissionList = authRolePermissionService.queryAllByCondition(authRolePermission);
            List<Long> permissionIds = authRolePermissionList.stream().map(AuthRolePermission::getPermissionId).collect(Collectors.toList());
            List<AuthPermission> permissionList = authPermissionService.queryByRoleList(permissionIds);
            List<String> permissionKeyList = permissionList.stream().map(AuthPermission::getPermissionKey).collect(Collectors.toList());

            // 将游客权限缓存到redis中
            redisUtil.setNx(touristKey, JSONUtil.toJsonStr(permissionKeyList), CacheKey.AUTH_PERMISSION.getCacheTime(), CacheKey.AUTH_PERMISSION.getCacheTimeUnit());

            return permissionKeyList;
        }

        // 从缓存中取出权限
        String permission = redisUtil.buildKey(CacheKey.AUTH_PERMISSION.getCachePrefix(), userName);
        String permissionValue = redisUtil.get(permission);
        // 判断缓存中是否存在该用户的权限
        if (StringUtils.isNotBlank(permissionValue)) {
            // 存在
            List<AuthPermission> permissionList = new Gson().fromJson(permissionValue, new TypeToken<List<AuthPermission>>() {
            }.getType());
            List<String> authList = permissionList.stream().map(AuthPermission::getPermissionKey).collect(Collectors.toList());
            return authList;
        }

        // 不存在
        List<String> authList = new LinkedList<>();

        /**
         * 根据前端传的用户名查出该用户的id
         */
        AuthUser authUser = new AuthUser();
        authUser.setUsername(userName);
        AuthUser user = authUserService.queryByCondition(authUser);
        if (Objects.isNull(user)) {
            return Collections.emptyList();
        }

        Long userId = user.getId();

        /**
         * 查询当前用户是什么角色，根据角色查询角色相应的权限  (查询用户角色关联表）
         */

        AuthUserRole authUserRole = new AuthUserRole();
        authUserRole.setUserId(userId);
        List<AuthUserRole> userRole = authUserRoleService.queryAllByCondition(authUserRole);

        /**
         *  根据用户角色关联表中的角色id，到角色表中查出该用户所拥有的角色
         */
        // 当前用户的所有角色Id
        List<Long> userRoleIds = userRole.stream().map(AuthUserRole::getRoleId).collect(Collectors.toList());
        List<AuthRole> authRoleList = authRoleService.queryByRoleList(userRoleIds);

        /**
         *   将用户角色缓存到redis中
         */
        String roleKey = redisUtil.buildKey(CacheKey.AUTH_ROLE.getCachePrefix(), authUser.getUsername());
        String roleCache = redisUtil.get(roleKey);
        if (StringUtils.isBlank(roleCache)) {
            redisUtil.setNx(roleKey, new Gson().toJson(authRoleList), CacheKey.AUTH_ROLE.getCacheTime(), CacheKey.AUTH_ROLE.getCacheTimeUnit());
        }

        /**
         * 根据上面查到的用户角色Id，到角色权限关联表从查出所有的权限Id，然后根据查出来的权限Id去查出对应的权限
         */

        List<AuthRolePermission> authRolePermissionList = authRolePermissionService.queryByRoleIdList(userRoleIds);
        List<Long> authPermissionIds = authRolePermissionList.stream().map(AuthRolePermission::getPermissionId).distinct().collect(Collectors.toList());


        /**
         * 缓存用户权限所需要的list
         */
        List<AuthPermission> cachePermissionList = new LinkedList<>();

        /**
         * 组装用户权限
         */
        authPermissionIds.forEach(permissionId -> {
            AuthPermission authPermission = authPermissionService.queryById(permissionId);
            cachePermissionList.add(authPermission);
            authList.add(authPermission.getPermissionKey());
        });

        // 将用户权限缓存到redis中
        String permissionKey = redisUtil.buildKey(CacheKey.AUTH_PERMISSION.getCachePrefix(), authUser.getUsername());
        redisUtil.set(permissionKey, new Gson().toJson(cachePermissionList));

        return authList;
    }
}
